package cn.microven.mindmap.components.part;

import cn.microven.mindmap.components.line.MapLine;
import cn.microven.mindmap.components.node.AbstractMapNode;
import cn.microven.mindmap.oprations.AddLeafOperation;
import cn.microven.mindmap.oprations.RemoveLeafOperation;
import cn.microven.mindmap.struture.MindMap;
import javafx.geometry.Pos;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.util.Pair;

import java.util.Vector;

public class BothSideMapPart extends MapPart {

    protected VBox lVBox;

    protected Pane lLinesBox;

    protected Vector<Pair<MapLine,Part>> leftLeaves = new Vector<>();

    protected Vector<Pair<MapLine,Part>> rightLeaves = new Vector<>();

    /**
     * 构造方法
     *
     * @param root 根节点
     */
    public BothSideMapPart(AbstractMapNode root) {
        super(root);
        this.level = 1;
    }

    @Override
    protected void initLayout() {
        //添加左边布局
        lVBox = new VBox();
        lLinesBox = new Pane();
        this.getChildren().addAll(lVBox,lLinesBox,root,linesBox,vBox);

        lVBox.setAlignment(Pos.CENTER_RIGHT);
        vBox.setAlignment(Pos.CENTER_LEFT);
        this.setAlignment(Pos.CENTER_LEFT);
        
        lVBox.spacingProperty().bindBidirectional(vBox.spacingProperty());

        //绑定vBox高度和linesBox高度
        lVBox.heightProperty().addListener(((observableValue, number, t1) ->{
            lLinesBox.setPrefHeight((Double)t1);
        }));

        //连线区域是否可见由vBox决定
        lLinesBox.visibleProperty().bind(lVBox.visibleProperty());
        lLinesBox.managedProperty().bind(lVBox.managedProperty());
        lVBox.visibleProperty().bindBidirectional(vBox.visibleProperty());
        lVBox.managedProperty().bindBidirectional(vBox.visibleProperty());
        lLinesBox.setPrefWidth(100);

        //同步左右高度
        vBox.heightProperty().addListener((change,number,t1)->{
            adjustHeight();
        });
        lVBox.heightProperty().addListener((change,number,t1)->{
            adjustHeight();
        });
    }

    /**
     * 统一高度
     */
    private void adjustHeight() {
        if (vBox.getHeight() > lVBox.getHeight()) {
            lLinesBox.setPrefHeight(vBox.getHeight());
//            lLinesBox.setPrefHeight(vBox.getHeight());
            lVBox.setPrefHeight(vBox.getHeight());
        }
        else {
            lLinesBox.setPrefHeight(lVBox.getHeight());
//            lLinesBox.setMaxHeight(lVBox.getHeight());
            vBox.setPrefHeight(lVBox.getHeight());
        }
    }

    @Override
    protected void bindIntersection() {
        leftIntersectionY = rightIntersectionY = root.layoutYProperty().add(root.heightProperty().divide(2));
    }

    @Override
    public void addLeaf() {
        if (MindMap.getInstance().getLayout().equals("Right")) {
            addRightLeaf(new RightMapPart(MindMap.getInstance().getDefaultNode().clone()));
        }
        if (MindMap.getInstance().getLayout().equals("Left")) {
            addLeftLeaf(new LeftMapPart(MindMap.getInstance().getDefaultNode().clone()));
        }
        if (MindMap.getInstance().getLayout().equals("BothSide")) {
            if (rightLeaves.size() > leftLeaves.size()) {
                addLeftLeaf(new LeftMapPart(MindMap.getInstance().getDefaultNode().clone()));
            } else {
                addRightLeaf(new RightMapPart(MindMap.getInstance().getDefaultNode().clone()));
            }
        }
    }

    public void addRightLeaf(Part nodePart) {
        //添加节点
        RightMapPart node = (RightMapPart) nodePart;
        node.setParentPart(this);

        MapLine line = connectRightLine(node);
        Pair<MapLine, Part> pair = new Pair<>(line, node);

        //执行操作
        AddLeafOperation alo = new AddLeafOperation(this, rightLeaves, vBox, linesBox, pair);
        alo.start();
    }

    public void addLeftLeaf(Part nodePart) {
        LeftMapPart node = (LeftMapPart) nodePart;
        node.setParentPart(this);

        MapLine line = connectLeftLine(node);
        Pair<MapLine, Part> pair = new Pair<>(line, node);

        //执行操作
        AddLeafOperation alo = new AddLeafOperation(this, leftLeaves, lVBox, lLinesBox, pair);
        alo.start();
    }

    protected MapLine connectRightLine(Part node){
        return connectLine(node);
    }

    public VBox getLVBox() {
        return lVBox;
    }

    public Pane getLLinesBox() {
        return lLinesBox;
    }

    public Vector<Pair<MapLine, Part>> getLeftLeaves() {
        return leftLeaves;
    }

    public Vector<Pair<MapLine, Part>> getRightLeaves() {
        return rightLeaves;
    }

    protected MapLine connectLeftLine(Part node) {
        //初始化连线连线
        MapLine line = new MapLine();
        line.getQuad().controlXProperty().bind(line.startXProperty().add(line.endXProperty().divide(10)));

        //设置开始横坐标
        line.setEndX(2);
        line.startXProperty().bind(lLinesBox.widthProperty().subtract(2));

        //绑定连线的起点和终点，与节点的连接点相对应
        line.startYProperty().bind(this.getLeftIntersectionY());
        line.endYProperty().bind(node.getRightIntersectionY());

        return line;
    }

    @Override
    public String getType() {
        return "BothSideMapPart";
    }

    @Override
    public void removeLeaf(Part node) {
        Pair<MapLine, Part> p = null;
        for (Pair<MapLine, Part> pair : this.getBothSideLeaves()) {
            if (pair.getValue() == node) {
                p = pair;
            }
        }
        if (p != null) {
            if (rightLeaves.contains(p)) {
                RemoveLeafOperation rlo = new RemoveLeafOperation(this,rightLeaves,vBox,linesBox,p);
                rlo.start();
            }
            if (leftLeaves.contains(p)) {
                RemoveLeafOperation rlo = new RemoveLeafOperation(this,leftLeaves,lVBox,lLinesBox,p);
                rlo.start();
            }
        }
    }

    @Override
    public void addLeaf(Part nodePart) {
        if (vBox.getHeight() > lVBox.getHeight()) {
            addLeftLeaf(nodePart);
        }
        else {
            addRightLeaf(nodePart);
        }
    }

    public Vector<Pair<MapLine, Part>> getBothSideLeaves() {
        Vector<Pair<MapLine, Part>> all = new Vector<>();
        all.addAll(this.getLeftLeaves());
        all.addAll(this.getRightLeaves());
        return all;
    }

    @Override
    public int getLevel() {
        return 1;
    }
}
